package com.hh.job;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.StrPool;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hh.entity.domain.Thumb;
import com.hh.entity.enums.ThumbTypeEnum;
import com.hh.mapper.BlogMapper;
import com.hh.service.ThumbService;
import com.hh.utils.RedisKeyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * com.hh.job
 * 定时将Redis中的点赞数据同步到数据库
 *
 * @author hanhui
 * @version 1.0
 * @date 2025/8/1 12:30
 **/
@Component
@Slf4j
public class SyncThumb2DBJob {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    ThumbService thumbService;
    @Resource
    BlogMapper blogMapper;

    @Scheduled(fixedRate = 10000)
    @Transactional(rollbackFor = Exception.class)
    public void run() {
        log.info("定时任务开始执行，将Redis中的点赞数据同步到数据库");
        DateTime nowDate = DateUtil.date();
        int second = (DateUtil.second(nowDate) / 10 - 1) * 10;
        if (second == -10) {
            second = 50;
            nowDate = DateUtil.offsetMinute(nowDate, -1);
        }
        String date = DateUtil.format(nowDate, "HH:mm") + ":" + second;
        log.info("当前时间：{}", date);
        syncThumb2DBByDate(date);
        log.info("定时任务执行结束，将Redis中的点赞数据同步到数据库");
    }

    @Async("taskExecutor")
    @Transactional(rollbackFor = Exception.class)
    public void syncThumb2DBByDate(String date) {
        String tempThumbKey = RedisKeyUtil.getTempThumbKey(date);
        Map<Object, Object> entries = redisTemplate.opsForHash().entries(tempThumbKey);
        boolean empty = CollUtil.isEmpty(entries);
        Map<Long, Long> blogThumbMap = new HashMap<>();
        if (empty) {
            return;
        }
        ArrayList<Thumb> thumbList = new ArrayList<>();
        LambdaQueryWrapper<Thumb> queryWrapper = new LambdaQueryWrapper<>();
        boolean hasDecr = false;
        for (Object userIdBlogIdObj : entries.keySet()) {
            try {
                String userIdBlogId = (String) userIdBlogIdObj;
                String[] userIdAndBlogId = userIdBlogId.split(StrPool.COLON);
                Long userId = Long.valueOf(userIdAndBlogId[0]);
                Long blogId = Long.valueOf(userIdAndBlogId[1]);
                Integer thumbType = Integer.valueOf(entries.get(userIdBlogId).toString());
                if (thumbType == ThumbTypeEnum.INCR.getValue()) {
                    Thumb thumb = new Thumb();
                    thumb.setUserId(userId);
                    thumb.setBlogId(blogId);
                    thumbList.add(thumb);
                    blogThumbMap.put(blogId, blogThumbMap.getOrDefault(blogId, 0L) + 1L);
                } else if (thumbType == ThumbTypeEnum.DECR.getValue()) {
                    hasDecr = true;
                    queryWrapper.or().eq(Thumb::getUserId, userId).eq(Thumb::getBlogId, blogId);
                    blogThumbMap.put(blogId, blogThumbMap.getOrDefault(blogId, 0L) - 1L);
                } else {
                    if (thumbType == ThumbTypeEnum.NON.getValue()) {
                        log.warn("数据异常:{}", userId + ":" + blogId + ":" + thumbType);
                    }
                    continue;
                }
            } catch (NumberFormatException e) {
                log.error("解析Redis中的点赞数据失败，userIdBlogId: {}", userIdBlogIdObj, e);
            }
        }
        thumbService.saveBatch(thumbList);
        if (hasDecr) {
            thumbService.remove(queryWrapper);
        }
        if (!blogThumbMap.isEmpty()) {
            blogMapper.batchUpdateThumbCount(blogThumbMap);
        }
        deleteTempThumbKey(tempThumbKey);
        log.info("定时任务结束执行，将Redis中的点赞数据同步到数据库");
    }


    @Async
    public void deleteTempThumbKey(String tempThumbKey) {
        log.info("异步任务开始");
        redisTemplate.delete(tempThumbKey);
        log.info("异步任务结束");
    }
}
